﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Windows.Controls;
using TinyEngine.Editor.Extensibility;
using System.Diagnostics;
using System.Windows;

namespace TinyEngineEditor
{
    public class PluginHolder
    {
        public Assembly Assembly { get; set; }
        public string Name { get; set; }
        public string Path { get; set; }
        public List<IPlugin> Plugins { get; set; }
        public PluginHolder()
        {
            Plugins = new List<IPlugin>();
        }
    }

    public class PluginManager
    {
        static Dictionary<string, PluginHolder> Plugins = new Dictionary<string, PluginHolder>();
        public static void LoadPlugins()
        {
            Trace.WriteLine("Loading plugins");
            var plugins = Properties.Settings.Default.Plugins;

            foreach (var plugin in plugins)
            {
                var split = plugin.Split('|');
                var name = split[0];
                var path = split[1];

                Trace.WriteLine(string.Format("Loading plugin {0} ({1})", name, path));

                PluginHolder p = new PluginHolder()
                {
                    Name = name,
                    Path = path
                };

                var fullPath = Path.GetFullPath(p.Path);
                var asm = Assembly.LoadFile(fullPath);

                p.Assembly = asm;
                CreatePlugins(p);
                Plugins.Add(name, p);
            }

            RegisterPlugins();
        }

        public static Action<UserControl, Dock> MainWindowControlAdded;
        private static void RegisterPlugins()
        {
            Trace.WriteLine("Registering plugins");

            foreach (var item in Plugins.Values)
            {
                foreach (var plugin in item.Plugins)
                {
                    Trace.WriteLine("Initializing plugin - " + plugin.GetType().Name);

                    InitPlugin(plugin);
                }
            }
        }

        private static void InitPlugin(IPlugin plugin)
        {
            Application.Current.Dispatcher.BeginInvoke(new Action(
            delegate
            {
                plugin.Initialize();

                var control = plugin.CreateInEditorControl();
                if (control != null)
                {
                    Trace.WriteLine("Found in editor control - " + control.GetType().Name);
                    MainWindowControlAdded(control.Control, control.DockSide);
                    Trace.WriteLine("Added to dockside - " + control.DockSide);
                }
            }));

        }

        private static void CreatePlugins(PluginHolder p)
        {
            var types = p.Assembly.GetTypes();
            foreach (var type in types)
            {
                if (type.GetInterface(typeof(IPlugin).FullName, false) != null)
                {
                    Trace.WriteLine(string.Format("Found plugin type {0}", type.FullName));
                    var instance = p.Assembly.CreateInstance(type.FullName);
                    Trace.WriteLine(string.Format("Plugin created ({0})", type.FullName));
                    p.Plugins.Add(instance as IPlugin);
                }
            }
        }
    }
}
